﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;
using FernUniHagen.CompilerExtension.Attributes;


namespace LinqExample
{


    public class A
    {
        ////TODO: still need to make sure that only list etc can be used
        [Obsolete]
        [Any(typeof(List<>))]
        A a, c;

        [Any(typeof(List<>))]
        A anyField;

        [Option]
        A b;


        [Option]
        A optionField;

        [Option]
        public A optionProp
        {
            get;
            set;
        }

        [Any(typeof(List<>))]
        public A anyProp
        {
            get;
            set;
        }
        //[Option]
        //public A MethodDeclarationConversionOption()
        //{
        //    return null;
        //}

        //[Any(typeof(List<>))]
        //public A MethodDeclarationConversionAny()
        //{
        //    return null;
        //}


        //public void ParameterConversionOption([Option] A param)
        //{

        //}


        //public void ParameterConversionAny([Any(typeof(List<>))] A param)
        //{

        //}

        //public void RMult1()
        //{
        //    var test =  ^ optionField ^;
        //    var test2 = ^ anyField ^;


        //}


        //[Any(typeof(List<>))]
        //public A m([Any(typeof(List<>))]A a, Boolean b)
        //{

        //    if (b)
        //        return a;
        //    else
        //        return a;
        //    return a;
        //}

        //[Option]
        //public A m3()
        //{
        //    //    //List<A> d = new List<A>();

        //    //    //var test = from i in d
        //    //    //           where i.a == null
        //    //    //           select i;
        //    //    //var test = from t in aExternalClass
        //    //    //           where t.AClass != null
        //    //    //           select t;

        //    //    //use lambda expressions?
        //    var test = from t in b
        //               where t.a != null
        //               select t;

        //    return b;
        //}

        //[Option]
        //public A m6()
        //{
        //    return new A();
        //}

        ///// <summary>
        ///// @Text: example how to resolve a.b.c issues
        ///// </summary>
        ////public void TestMultipleTransformationsInOneStatement()
        ////{
        ////    //Conversion would not work as several rules would apply
        ////    var test = a.b.anyField;
        ////    //Instead divide the statement manually into junks:
        ////    var dummy = a.b;
        ////    test = dummy.anyField;
        ////}

        //public void CheckIdentity()
        //{
        //    //R-Ident1 option == option
        //    var test = b == optionField;

        //    //R-Ident2 any == option
        //    test = anyField == optionField;

        //    //R-Ident3 option == any
        //    test = optionField == anyField;

        //    //R-Ident4 any == any
        //    test = anyField == a;

        //    if (optionField == anyField && anyField == optionField)
        //    {

        //    }
        //    //[Obsolete]test = anyField == a;

        //}

        //[Any(typeof(List<>))]
        //public A m4([Any(typeof(List<>))]A d, [Any(typeof(List<>))]A b, [Option] A c)
        //{
        //    ////TODO: this.a.optionfield did not work 
        //    //// var test = a.optionField.a.optionField;
        //    //// a = new A();
        //    ////c = ([OptionAttribute] A) a;

        //    //R-TCast
        //    var typeCast = (object)a;

        //    //R-MCast1
        //    var anyToOption = (OptionAttribute)(A)a;

        //    //R-MCast2
        //    var mcast2 = (AnyAttribute)(Enumerable)a;

        //    //R-MCast3
        //    var optionToAny = (AnyAttribute)(List)optionField;

        //    ////var test = ([OptionAttribute] A) a;
        //    ////c = true == true ? null : (OptionAttribute A) a;
        //    ////translated return value (any any)
        //    //Conversion necessary because of aliases?
        //    return a;
        //}

        //[Any(typeof(List<>))]
        //public A returnTest1()
        //{
        //    //Apply Rule R-Return2
        //    return new A();
        //}

        //[Any(typeof(List<>))]
        //public A returnTest2()
        //{
        //    return a;
        //}

        //[Any(typeof(List<>))]
        //public A returnTest3([Any(typeof(IEnumerable<>))]A differentAny)
        //{
        //    //TODO: should call addrange()
        //    //translated return value any option
        //    return differentAny;
        //}

        //public void m2([Any(typeof(List<>))]A d)
        //{

        //    var test = new A();

        //    d += test;

        //    //R-Add1
        //    a += test;
        //    ////R-Add2
        //    a += a;

        //    ////R-Sub1
        //    a -= test;
        //    //R-Sub2
        //    a -= anyField;

        //    for (int i = 0; i <= 10; i++)
        //    {
        //        //Assignment Translation Any  = <Any with constructor call
        //        a = new A();
        //        //Assignment Translation Any  = <Any
        //        a = test;
        //        ////Assignment Translation Any = Any
        //        a = d;
        //        if (1 == 1)
        //        {
        //            a -= anyField;
        //        }
        //    }
        //    //Member Access option.option
        //    var testMemAccess = b.optionField;

        //    ////Member Access Expression Any.Option
        //    var testMemAccess2 = a.optionField;

        //    ////Member Access Expression Any.Any. Typen und Multiplicity wird noch nicht geprüft (testMemAccess3 müsste Any List<A> sein)
        //    var testMemAccess3 = a.anyField;

        //    ////Method call Parameter conversion
        //    var test1 = b.m3();
        //    b.m3();

        //    var test2 = a.m3();
        //    a.m3();

        //    //var test3 = a.m(a, true);
        //    //a.m(a, true);

        //    var test4 = a.m4(a, a, b);
        //    a.m4(a, a, b);

        //    //FIX THIS
        //    //var bla = optionField == anyField;
        //    //var test = a.MultipleReplacementsCheck(optionField == anyField);

        //}

        //public bool MultipleReplacementsCheck(bool test)
        //{
        //    return true;
        //}

        ///// <summary>
        /////
        ///// </summary>
        //public void test([Any(typeof(List<>))] A test)
        //{
        //    //Regeltechnisch nicht abgedeckt...muß eine Regel her?
        //    //var bla = test;
        //    //var blub = a;

        //    var bla = test.a;
        //    var blub = a.a;
        //}


    }


}


